home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Languages / MPW Oberon 2.1168 / OExamples / ResEqual.mod < prev    next >
Encoding:
Text File  |  1995-07-03  |  17.6 KB  |  540 lines  |  [TEXT/MPS ]

  1. (*[n+,u+,r+,d+,#+,j=13-/40/1o,t=2,o=95] PasMat formatting options*)
  2.  
  3. (*------------------------------------------------------------------------------
  4.  
  5. FILE ResEqual.p
  6.  Copyright Apple Computer, Inc. 1986, 1987
  7.  All rights reserved.
  8.  
  9. NAME
  10.  ResEqual -- compare resources in two files
  11.  
  12. SYNOPSIS
  13.  resequal [-p] file1 file2
  14.  
  15. DESCRIPTION
  16.  "resequal" compares the resources in two files. If both files contain
  17.  the same resources, and all of the resources are equal, it runs silently.
  18.  It reports resources found in only one of the files, resources of
  19.  different sizes, resources with different contents, and differing
  20.  resource attributes. Output is written to standard output. The -p
  21.  option writes progress information to diagnostic output.
  22. ------------------------------------------------------------------------------*)
  23. (*$R-*)                                                                  (* Turn off range checking*)
  24. MODULE ResEqual;
  25.  
  26. IMPORT SYSTEM, Types, Resources, Memory, Files, DWrite, Write, CursorCtl,
  27.        IntEnv, Signal, SegLoad, PasLibIntf, Strings;
  28.  
  29. (* CONST
  30.       Version          = '2.1';                            Current version, now in 'vers' resource*)
  31.     CONST
  32.         RC_Normal=0; RC_ParmErrs=1; RC_DontMatch=2; (*RC_Abort=3;*)
  33.     VAR
  34.         file1Ref:      INTEGER;                          (* the refnums for our files *)
  35.         file2Ref:      INTEGER;
  36.         curRes:          INTEGER;
  37.         file1Name:     Types.Str255;                             (* the names of the files we're comparing*)
  38.         file2Name:     Types.Str255;
  39.         quiet:             BOOLEAN;                          (* True ==> no info on Diagnostic file*)
  40.         progName:      Types.Str255;                             (* Program's file name*)
  41.         interrupted: BOOLEAN;                          (* True ==> interrupted (Cmd "." pressed)*)
  42.         retCode:         INTEGER; (*Return codes*)
  43.     (*$J+ external variables*)
  44.         OUTPUT:      LONGINT; (* standard output *)
  45.     (*$J- external variables*)
  46.  
  47.         (*[j=0] PasMat formatting option*)
  48.  
  49.  (**----------------------------------*
  50.  | Stop - terminate execution  |
  51.  *----------------------------------**)
  52.  
  53.     PROCEDURE Stop(msg: ARRAY OF CHAR);
  54.  
  55.         BEGIN                                                          (*Stop*)
  56.             IF msg[0]#0X THEN
  57.                 PasLibIntf.PLFlush(OUTPUT);
  58.                 DWrite.Ln;
  59.                 DWrite.String(msg);
  60.                 DWrite.Ln
  61.             END;
  62.  
  63.             IF interrupted THEN HALT(-9) END;
  64.     (* don't worry about closing the files we opened.  The Shell
  65.         will do so if appropriate.*)
  66.             HALT(retCode);                      (*exit, returning the appropriate status code*)
  67.         END Stop;                                                             (*Stop*)
  68.  
  69.  (**--------------------------------------*
  70.  | Intr - Process external interrupt    |
  71.  | this routine is passed to IEsigset |
  72.  *--------------------------------------**)
  73.  
  74.     (*$Calling Pascal*)
  75.     PROCEDURE Intr;
  76.     BEGIN
  77.         interrupted := TRUE;                         (*we test this switch periodically*)
  78.     END Intr;
  79.     (*$Calling Oberon*)
  80.  
  81.     (*$S Init*)
  82.  
  83. (**-------------------------------------------------------------*
  84.  | SyntaxError - Report an error in parameters or options |
  85.  *-------------------------------------------------------------**)
  86.  
  87.     PROCEDURE SyntaxError(suffix: ARRAY OF CHAR);
  88.         VAR msg: ARRAY 256 OF CHAR;
  89.         BEGIN                                                          (*SyntaxError*)
  90.             PasLibIntf.PLFlush(OUTPUT);
  91.             DWrite.String('### ');
  92.             DWrite.String(progName);
  93.             DWrite.String(' - ');
  94.             DWrite.String(suffix);
  95.             DWrite.Ln;
  96.             COPY("# Usage: ", msg); APPEND(progName, msg);
  97.             APPEND(" file1 file2 [-p]", msg);
  98.             Stop(msg);
  99.         END SyntaxError;                                                             (*SyntaxError*)
  100.  
  101.  (**-----------------------------------*
  102.  | LetterOpt - Set a letter option |
  103.  *-----------------------------------**)
  104.  
  105.     PROCEDURE LetterOpt(opt: CHAR; (*VAR*) argVIndex: INTEGER);
  106.  (* note only one option is supported.  argVIndex is passed to
  107.  this routine so options that have arguments can 'eat' them*)
  108.         VAR msg: ARRAY 256 OF CHAR;
  109.         BEGIN
  110.             IF (opt='p') OR (opt='P') THEN
  111.                 quiet := FALSE
  112.             ELSE
  113.                 COPY(IntEnv.ArgV[argVIndex]^, msg);
  114.                 APPEND(" <invalid option>", msg);
  115.                 SyntaxError(msg);
  116.             END
  117.         END LetterOpt;
  118.  
  119.  (**---------------------------*
  120.  | Init - Tool initalization |
  121.  *---------------------------**)
  122.  
  123.     PROCEDURE Init;
  124.  
  125.         VAR
  126.             argVIndex, fileCount, holdIndex, i: INTEGER;
  127.             prevSig: Signal.SignalHandler;
  128.             versH: Files.VersRecHndl;
  129.             arg: Types.Str255;
  130.             versStr: Types.Str255;
  131.  
  132.         BEGIN
  133.             retCode := RC_Normal;
  134.  
  135.             interrupted := FALSE;                      (*becomes True when interrupted*)
  136.             prevSig := Signal.IEsignal(Signal.SIGINT, Intr);
  137.  
  138.             quiet := TRUE;
  139.             COPY(IntEnv.ArgV[0]^, progName);
  140.             retCode := RC_ParmErrs;
  141.  
  142.             fileCount := 0;
  143.             retCode := RC_ParmErrs;
  144.             file1Ref := - 1;                                 (* so we tell if the open works*)
  145.             file2Ref := - 1;                                 (* as above*)
  146.             argVIndex := 1;
  147.             WHILE argVIndex < IntEnv.ArgC DO              (*ArgC is the number of args plus one*)
  148.                 COPY(IntEnv.ArgV[argVIndex]^, arg);
  149.                 IF arg[0] # 0X THEN
  150.                     IF arg[1] = '-' THEN                 (* we have an option *)
  151.                         holdIndex := argVIndex;
  152.                         LetterOpt(arg[2], argVIndex);
  153.                         IF argVIndex # holdIndex THEN DEC(argVIndex) END; (* skip the increment of argVIndex below*)
  154.                     ELSE                                                 (* it must be a file to open*)
  155.                         INC(fileCount);
  156.                         IF fileCount = 1 THEN
  157.                             COPY(IntEnv.ArgV[argVIndex]^, file1Name)
  158.                         ELSE
  159.                             COPY(IntEnv.ArgV[argVIndex]^, file2Name)
  160.                         END;
  161.                     END;
  162.                 END;
  163.                 INC(argVIndex)
  164.             END;
  165.             IF fileCount # 2 THEN SyntaxError('Invalid Parameters') END;
  166.             curRes := Resources.CurResFile();
  167.  
  168.             IF ¬quiet THEN
  169.                 DWrite.Ln;
  170.  
  171.                 versH := Files.VersRecHndl(Resources.Get1Resource(LONG("vers"), 1)); (*get the version from the 'vers' resource*)
  172.  
  173.                 IF versH # NIL THEN
  174.                     i:=1;
  175.                     WHILE i<=ORD(versH.shortVersion[0]) DO
  176.                         versStr[i-1]:=versH.shortVersion[i]; INC(i)
  177.                     END;
  178.                     versStr[i]:=0X;
  179.                     Resources.ReleaseResource(Types.Handle(versH));
  180.                     COPY(progName, arg); APPEND("  (Ver ", arg);
  181.                     APPEND(versStr, arg); APPEND(")", arg);
  182.                     DWrite.String(arg)
  183.                 ELSE
  184.                     COPY(progName, arg); APPEND("  (Ver **unavailable**)", arg);
  185.                     DWrite.String(arg)
  186.                 END;
  187.  
  188.                 DWrite.Ln;
  189.                 DWrite.Ln;
  190.                 DWrite.Ln
  191.             END;
  192.  
  193.             Resources.SetResLoad(FALSE);                             (* keep preloads from loading*)
  194.             versStr:=file2Name; Strings.C2PStrProc(SYSTEM.ADR(versStr));
  195.             file2Ref := Resources.OpenRFPerm(versStr, 0, Files.fsRdPerm);
  196.             Resources.SetResLoad(TRUE);
  197.             IF file2Ref = - 1 THEN
  198.                 COPY("### ", arg); APPEND(progName, arg);
  199.                 APPEND(" - ", arg); APPEND("could not open ", arg);
  200.                 APPEND(file2Name, arg);
  201.                 Stop(arg)
  202.             END;
  203.             Resources.SetResLoad(FALSE);                             (* keep preloads from loading*)
  204.             versStr:=file1Name; Strings.C2PStrProc(SYSTEM.ADR(versStr));
  205.             file1Ref := Resources.OpenRFPerm(versStr, 0, Files.fsRdPerm);
  206.             Resources.SetResLoad(TRUE);
  207.             Resources.UseResFile(curRes);                          (* in case file2 opened, but file one doesn't*)
  208.             IF file1Ref = - 1 THEN
  209.                 COPY("### ", arg); APPEND(progName, arg);
  210.                 APPEND(" - ", arg); APPEND("could not open ", arg);
  211.                 APPEND(file1Name, arg);
  212.                 Stop(arg)
  213.             END;
  214.  
  215.             retCode := RC_Normal;
  216.  
  217.             CursorCtl.RotateCursor(0);
  218.             IF interrupted THEN Stop("") END;
  219.         END Init;
  220.  
  221.     (*$S Main*)
  222.  
  223.  (**-------------------------------------------------*
  224.     | ByteToStr - Convert a byte to a hex string    |
  225.     *-------------------------------------------------**)
  226.  
  227.     PROCEDURE ByteToStr(N: INTEGER; VAR s: ARRAY OF CHAR);
  228.         VAR d: INTEGER;
  229.         BEGIN
  230.             IF N = 0 THEN
  231.                 COPY("00", s);
  232.             ELSE
  233.                 s[2]:=0X; d:=BAND(ASH(N, -4), $F)+ORD("0");
  234.                 IF d>ORD("9") THEN INC(d, ORD("A")-ORD("9")-1) END;
  235.                 s[0]:=CHR(d); d:=BAND(N, $F)+ORD("0");
  236.                 IF d>ORD("9") THEN INC(d, ORD("A")-ORD("9")-1) END;
  237.                 s[1]:=CHR(d)
  238.             END
  239.         END ByteToStr;
  240.  
  241.     PROCEDURE DumpMem(firstStart, secondStart: Types.Ptr; offset, size: LONGINT);
  242.  
  243.         PROCEDURE DumpPtr(theStart: Types.Ptr);
  244.  
  245.             VAR
  246.                 count, len: INTEGER;
  247.                 limit: LONGINT;
  248.                 thePtr: Types.Ptr;
  249.                 theStr, byte: Types.Str255;
  250.                 b: Types.SignedByte;
  251.  
  252.             BEGIN
  253.                 limit := size - offset;
  254.                 IF limit > 16 THEN limit := 16 END;
  255.                 theStr := "";
  256.                 thePtr := theStart;
  257.                 FOR count := 1 TO SHORT(limit) DO
  258.                     SYSTEM.GET(LONGINT(thePtr), b); ByteToStr(b, byte);
  259.                     APPEND(byte, theStr); APPEND(" ", theStr);
  260.                     thePtr := Types.Ptr(LONGINT(thePtr) + 1)
  261.                 END;
  262.                 APPEND('    ', theStr);
  263.                 thePtr := theStart;
  264.                 len := LENGTH(theStr) + SHORT(limit);
  265.                 theStr[len] := 0X;
  266.                 FOR count := len - SHORT(limit) + 1 TO len DO
  267.                   SYSTEM.GET(LONGINT(thePtr), b);
  268.                     IF (ORD(' ')<=b) & (b<=ORD('z')) THEN
  269.                         theStr[count] := CHR(b)
  270.                     ELSE
  271.                         theStr[count] := '.'
  272.                     END;
  273.                     thePtr := Types.Ptr(LONGINT(thePtr) + 1)
  274.                 END;
  275.                 Write.String(theStr); Write.Ln
  276.             END DumpPtr;
  277.  
  278.         BEGIN
  279.             Write.String("Contents of resource in file 1 at offset ");
  280.             Write.Int(offset, 1); Write.Ln;
  281.             DumpPtr(firstStart);
  282.             Write.String("Contents of resource in file 2 at offset ");
  283.             Write.Int(offset, 1); Write.Ln;
  284.             DumpPtr(secondStart);
  285.             Write.Ln;
  286.         END DumpMem;
  287.  
  288.  (**--------------------------------------*
  289.  | DoIt -- check resources in each file |
  290.  *--------------------------------------**)
  291.  
  292.     PROCEDURE DoIt;                                          (* the guts of our program--in a procedure so the
  293.                                                                                 compiler can do register optimizations*)
  294.  
  295.         VAR
  296.             cursorCount: INTEGER;                      (* for our spinning cursor*)
  297.  
  298.             theType: Types.ResType;                              (* parameters for GetResInfo calls*)
  299.             theID: INTEGER;
  300.             theName: Types.Str255;
  301.  
  302.             theSize1, theSize2: LONGINT;
  303.             theAttr1, theAttr2: INTEGER;
  304.  
  305.  (**-------------------------------------------*
  306.  | CheckResources -- compare those resources |
  307.  *-------------------------------------------**)
  308.  
  309.         PROCEDURE CheckResources;
  310.  
  311.             VAR
  312.                 typeIndex, resIndex: INTEGER;  (* counters for our getindXXXX calls*)
  313.  
  314.                 theRes1, theRes2: Types.Handle;          (* handles for our resource compares*)
  315.                 clearRes1, clearRes2: BOOLEAN; (* call emptyhandle if True*)
  316.                 firstTime: BOOLEAN;                      (* have we written anything yet?*)
  317.                 res1State, res2State: Types.SignedByte; (* to save and restore MP flags*)
  318.  
  319.             PROCEDURE TellIt(message: ARRAY OF CHAR);
  320.  
  321.                 BEGIN
  322.                     IF firstTime THEN
  323.                         Write.Ln;
  324.                         Write.String("File #1: "); Write.String(file1Name); Write.Ln;
  325.                         Write.String("File #2: "); Write.String(file2Name); Write.Ln;
  326.                         Write.Ln;
  327.                         firstTime := FALSE;
  328.                         retCode := RC_DontMatch;
  329.                     END;
  330.                     Write.String(message); Write.Ln;
  331.                     Write.String("Resource Type = \034");
  332.                     Write.OSType(theType);
  333.                     Write.String("\034  ID = ");
  334.                     Write.Int(theID, 1);
  335.                     Write.Ln
  336.                 END TellIt;
  337.  
  338.             PROCEDURE TellAttr(theAttr: INTEGER);
  339.             
  340.             (* These constants are found in the Resource Manager chapter of 
  341.                 Inside Macintosh Vol I, page 111.  Only bits 1-6 of the low-order
  342.                 byte of the INTEGER are used for flags. The other bits of the
  343.                 INTEGER are reserved or ignored.  *)
  344.             BEGIN
  345.                     IF BAND(theAttr, $2) # 0 THEN Write.String('changed ') END;
  346.                     IF BAND(theAttr, $4) # 0 THEN Write.String('preload ') END;
  347.                     IF BAND(theAttr, $8) # 0 THEN Write.String('protected ') END;
  348.                     IF BAND(theAttr, $10) # 0 THEN Write.String('locked ') END;
  349.                     IF BAND(theAttr, $20) # 0 THEN Write.String('purgable ') END;
  350.                     IF BAND(theAttr, $40) # 0 THEN Write.String('sysHeap ') END;
  351.                     IF BAND(theAttr, $7E) = 0 THEN Write.String('-No flags set-') END;
  352.                     Write.Ln;
  353.                 END TellAttr;
  354.  
  355.  (**-------------------------------------------------*
  356.  | CheckEqual--compares contents of 2 handles     |
  357.  *-------------------------------------------------**)
  358.  
  359.             PROCEDURE CheckEqual(a, b: Types.Handle; size: LONGINT);
  360.  
  361.                 CONST
  362.                     maxBad = 10;
  363.  
  364.                 VAR
  365.                     count: LONGINT;
  366.                     srcB, trgB: Types.SignedByte;
  367.                     source, target: Types.Ptr;
  368.                     numBad: INTEGER;
  369.  
  370.                 BEGIN
  371.                     numBad := 0;                                 (* no problems so far*)
  372.                     source := MASTERPTR(a);
  373.                     target := MASTERPTR(b);
  374.                     count  := 0;
  375.                     WHILE count < size DO
  376.                         SYSTEM.GET(LONGINT(source), srcB);
  377.                         SYSTEM.GET(LONGINT(target), trgB);
  378.                         IF srcB # trgB THEN
  379.                             IF numBad = 0 THEN TellIt('Resources have different contents') END;
  380.                             DumpMem(source, target, count, size);
  381.                             numBad := numBad + 1;
  382.                             IF numBad >= maxBad THEN RETURN END;
  383.                             source := Types.Ptr(LONGINT(source) + 16);
  384.                             target := Types.Ptr(LONGINT(target) + 16);
  385.                             count := count + 16;
  386.                         ELSE
  387.                             source := Types.Ptr(LONGINT(source) + 1);
  388.                             target := Types.Ptr(LONGINT(target) + 1);
  389.                             count := count + 1;
  390.                         END;
  391.                     END;
  392.                 END CheckEqual;
  393.  
  394.             BEGIN
  395.                 firstTime := TRUE;
  396.                 Resources.UseResFile(file1Ref);
  397.                 FOR typeIndex := 1 TO Resources.Count1Types() DO (* countTypes counts Types in 1st file*)
  398.                     Resources.UseResFile(file1Ref);
  399.                     Resources.Get1IndType(theType, typeIndex); (* get the next type*)
  400.                     FOR resIndex := 1 TO Resources.Count1Resources(theType) DO
  401.                         Resources.UseResFile(file1Ref);
  402.                         Resources.SetResLoad(FALSE);                 (* we want the info, but not the data right now*)
  403.                         theRes1 := Resources.Get1IndResource(theType, resIndex);
  404.                         Resources.SetResLoad(TRUE);                  (* so loadseg will really get our segments*)
  405.                         Resources.UseResFile(curRes);
  406.  
  407.                         cursorCount := cursorCount + 1;
  408.                         CursorCtl.RotateCursor(cursorCount);
  409.  
  410.                         IF interrupted THEN Stop("") END; (* in case the user hit command-period*)
  411.  
  412.                         (* we want the resource ID and name*)
  413.                         Resources.GetResInfo(theRes1, theID, theType, theName);
  414.                         Resources.UseResFile(file2Ref);          (* now we will try to find a match in the other file*)
  415.                         Resources.SetResLoad(FALSE);                 (* we want the info, but not the data right now*)
  416.                         theRes2 := Resources.Get1Resource(theType, theID); (* resLoad is FALSE*)
  417.                         Resources.SetResLoad(TRUE);                  (* so loadseg will really get our segments*)
  418.                         Resources.UseResFile(curRes);              (* from our resource file*)
  419.  
  420.                         IF ~quiet THEN
  421.                             PasLibIntf.PLFlush(OUTPUT);
  422.                             DWrite.String("Checking resource ");
  423.                             DWrite.Int(theType, 1);
  424.                             DWrite.String(" #");
  425.                             DWrite.Int(theID, 1);
  426.                             DWrite.Ln
  427.                         END;
  428.  
  429.                         IF theRes2 = NIL THEN      (*not in our file*)
  430.                             TellIt('In 1 but not in 2');
  431.                             Write.Ln;
  432.  
  433.                         ELSE
  434.                             theAttr1 := Resources.GetResAttrs(theRes1);
  435.                             theAttr2 := Resources.GetResAttrs(theRes2);
  436.                             (* Use the $7E constant since only bits 1-6 are significant.*)
  437.                             IF BAND(theAttr1, $7E) # BAND(theAttr2, $7E) THEN
  438.                                 TellIt('Resources have different flags');
  439.                                 Write.String('Flags 1 = ');
  440.                                 TellAttr(theAttr1);
  441.                                 Write.String('Flags 2 = ');
  442.                                 TellAttr(theAttr2);
  443.                                 Write.Ln;
  444.                             END;
  445.                             theSize1 := Resources.SizeResource(theRes1);
  446.                             theSize2 := Resources.SizeResource(theRes2);
  447.                             IF theSize1 # theSize2 THEN
  448.                                 TellIt('Resources are different sizes');
  449.                                 Write.String("Size 1 = ");
  450.                                 Write.Int(theSize1, 1);
  451.                                 Write.String("  Size 2 = ");
  452.                                 Write.Int(theSize2, 1);
  453.                                 Write.Ln;
  454.                             ELSE
  455.                                 clearRes1 := MASTERPTR(theRes1) = NIL;
  456.                                 Resources.LoadResource(theRes1); (* resload is TRUE, so get the data--add check for
  457.                                                                                 reserr*)
  458.                                 IF Resources.ResError() # 0 THEN
  459.                                     Stop('Could not load resource');
  460.                                 END;
  461.                                 res1State := Memory.HGetState (theRes1); (* save current MP flags*)
  462.                                 Memory.HNoPurge(theRes1);        (* don't let it be purged*)
  463.                                 clearRes2 := MASTERPTR(theRes2) = NIL;
  464.                                 Resources.LoadResource(theRes2); (* as above*)
  465.                                 IF Resources.ResError() # 0 THEN
  466.                                     Stop('Could not load resource');
  467.                                 END;
  468.                                 res2State := Memory.HGetState (theRes2); (* save current MP flags*)
  469.                                 Memory.MoveHHi(theRes2);
  470.                                 Memory.HLock(theRes2);     (* lock it down*)
  471.                                 Memory.MoveHHi(theRes1);
  472.                                 Memory.HLock(theRes1);     (* this one as well*)
  473.                                 CheckEqual(theRes1, theRes2, theSize1);
  474.                                 Memory.HSetState(theRes1,res1State);
  475.                                 Memory.HSetState(theRes2,res2State);
  476.                                 IF clearRes1 THEN Memory.EmptyHandle(theRes1) END; (* free memory if we loaded resource*)
  477.                                 IF clearRes2 THEN Memory.EmptyHandle(theRes2) END; (* as above*)
  478.                             END                                      (*ELSE sizes equal*)
  479.                         END;                                         (*ELSE res in both files*)
  480.                     END;
  481.                 END;
  482.  
  483.                 Resources.UseResFile(file2Ref);
  484.                 FOR typeIndex := 1 TO Resources.Count1Types() DO (* countTypes counts Types in 2nd file*)
  485.                     Resources.UseResFile(file2Ref);
  486.                     Resources.Get1IndType(theType, typeIndex); (* get the next type*)
  487.                     FOR resIndex := 1 TO Resources.Count1Resources(theType) DO
  488.                         Resources.UseResFile(file2Ref);
  489.                         Resources.SetResLoad(FALSE);                 (* we want the info, but not the data right now*)
  490.                         theRes2 := Resources.Get1IndResource(theType, resIndex);
  491.                         Resources.SetResLoad(TRUE);                  (* so loadseg will really get our segments*)
  492.                         Resources.UseResFile(curRes);
  493.  
  494.                         cursorCount := cursorCount + 1;
  495.                         CursorCtl.RotateCursor(cursorCount);
  496.  
  497.                         IF interrupted THEN Stop('') END; (* in case the user hit command-period*)
  498.  
  499.                         (* we want the resource ID and name*)
  500.                         Resources.GetResInfo(theRes2, theID, theType, theName);
  501.                         Resources.UseResFile(file1Ref);          (* now we will try to find a match in the other file*)
  502.                         Resources.SetResLoad(FALSE);                 (* we want the info, but not the data right now*)
  503.                         theRes1 := Resources.Get1Resource(theType, theID); (* resLoad is FALSE*)
  504.                         Resources.SetResLoad(TRUE);                  (* so loadseg will really get our segments*)
  505.                         Resources.UseResFile(curRes);              (* from our resource file*)
  506.  
  507.                         IF ¬quiet THEN
  508.                             PasLibIntf.PLFlush(OUTPUT);
  509.                             DWrite.String("Checking resource ");
  510.                             DWrite.Int(theType, 1);
  511.                             DWrite.String(" #");
  512.                             DWrite.Int(theID, 1);
  513.                             DWrite.Ln
  514.                         END;
  515.  
  516.                         IF theRes1 = NIL THEN      (*not in our file*)
  517.                             TellIt('In 2 but not in 1');
  518.                             Write.Ln;
  519.                         END
  520.  
  521.                     END;
  522.                 END;
  523.             END CheckResources;
  524.  
  525.         BEGIN
  526.             cursorCount := 0;                              (* prepare to spin that cursor*)
  527.             CheckResources;
  528.             Stop('');
  529.         END DoIt;
  530.  
  531.  (**----------------------------*
  532.  | ResEqual -- main program  |
  533.  *----------------------------**)
  534. (*$MAIN*)
  535.     BEGIN
  536.         Init;                                                          (* sets up world, opens our resource files*)
  537.         SegLoad.UnloadSeg(SYSTEM.ADR(Init));                                  (* release our initialization segment*)
  538.         DoIt;                                                          (* and call our routine*)
  539.     END ResEqual.
  540.